#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"


static char tempname[128];
static char newString[20];

void numToString(int num){
	int num2 = num;
	int i;
	//int j = 0;
	int count = 0; //will hold the number of digits in num
	if (num==0) {
		newString[0]= 48;
		newString[1]=0;
	}
	else{
		while (num!=0){
			num = num/10;
			count = count+1;
		}
	

		for (i = count-1; i>=0; i--){
			newString[i]= (num2 % 10) + 48;	
			num2 = num2 / 10;
		}
		newString[count]=0;
	}
}


void
shirshur(char* p2){

	char* p1 = "FibTest<";
	char* p3 = ">.txt";

	int l1 = strlen(p1);
	int l2 = strlen(p2);

	strcpy(tempname, p1);
	strcpy(tempname + l1, p2);
	strcpy(tempname + l1 + l2, p3);
}

int
main(int argc, char *argv[]){

// numToString(atoi(argv[1]));
// shirshur(newString);
// printf(1, tempname);
// exit();
	int numOfElem = atoi(argv[1]);
	int i;
	int pid=-1;
	int cid;
//	int j;
	int wtime;
	int rtime;
	int wtimes[numOfElem];
	int rtimes[numOfElem];
	int avgwtime=0;
	int avgrtime=0;
	int avgttime=0;
	int counter;
	int ttime;
	int fst, sec, tmp, k, fd;
	char temp[2];
	char n1[100], n2[100];
	int num1, num2, m;
	//char num1s[100], num2s[100];
	int flag = 0; // will hold how many numbers read from file
//	char* filename;

				
				
	for (i=0; i<numOfElem; i++){
		if((pid=fork())==0) {
			cid = i;
			if ((cid % 2) == 1) {
				fst = 0;
				sec = 1;

				for (k = 0; k < cid; k++){
					tmp = sec;
					sec = sec + fst;
					fst = tmp;
				}
			}
			else {
				
				numToString(cid);
				shirshur(newString);
				fd = open(tempname, O_CREATE | O_RDWR);
				for (k = 0; k <= cid; k++){
					if (k==0){
						write(fd, "0", 1);
						close(fd);
						printf(1, "FibTest<%d> <%d>,<%d>\n", cid, 0, 0);
					}
					if (k==1){
						fd = open(tempname,  O_CREATE |O_RDWR);
						write(fd, "0\n1\n", 4);
					//	read(fd, temp, 4);
					//	printf(1, temp);
						close(fd);
						printf(1, "FibTest<%d> <%d>,<%d>\n", cid, 0, 1);
						
					}
					if (k > 1) { //not base cases
						fd = open(tempname, O_RDONLY);
						for (m=0; ((flag < 1) && (m < 100)); m++ ){
							read(fd, temp, 1);
							if (temp[0] != '\n'){
								n1[m] = temp[0];
// 								printf(1, "hiiiiiiiiiiiii    %s", &n1[m]);
							}
							else {
								flag = 1;
								n1[m] = 0;
							}
						}
						//printf(1, "hiiiiiiiiiiiii    %s", temp);
						for (m=0; (flag < 2) && (m < 100) ; m++ ){
							read(fd, temp, 1);
							if(temp[0] != '\n'){
								n2[m]=temp[0];
								//printf(1, "hiiiiiiiiiiiii    %s", temp);
							}
							else{
								flag = 2;
								n2[m]=0;
							}
						}
						
						//now n1 and n2 hold the string of the numbers in the file
						num1 = atoi(n1);
						num2 = atoi(n2);
						
						tmp = num2;
						num2 = num1 + num2;
						num1 = tmp;
						
						close(fd);
						fd = open(tempname, O_RDWR);
						numToString(num1);
						write(fd, newString, strlen(newString));
						write(fd, "\n",1);
						numToString(num2);
						write(fd, newString, strlen(newString));
						write(fd, "\n",1);

						close(fd);
						printf(1, "FibTest<%d> <%d>,<%d>\n", cid, num1, num2);
					}

					flag = 0;
					
				}



			
			
			}
			printf(1, "FibTest: proc %d finished its calculation\n", cid);
			exit();
		}
	}


	if (pid > 0){
		for (counter = 0; counter<numOfElem; counter++){
			wait2(&wtime, &rtime);
			wtimes[counter] = wtime;
			rtimes[counter] = rtime;
		}
		
		for (counter = 0; counter<numOfElem; counter++){
			avgwtime = avgwtime + wtimes[counter];
			avgrtime = avgrtime + rtimes[counter];
			avgttime = avgttime + rtimes[counter] + wtimes[counter];
		}
		
		avgwtime = avgwtime / numOfElem;
		avgrtime = avgrtime / numOfElem;
		avgttime = avgttime / numOfElem;
		
		printf(1, "Average waiting time: %d\n", avgwtime);
		printf(1, "Average running time: %d\n", avgrtime);
		printf(1, "Average turnaround time: %d\n", avgttime);
		
		for (counter = 0; counter<numOfElem; counter++){
			ttime = wtimes[counter] + rtimes[counter];
			printf(1, "Waiting: %d , Running: %d , Turnaround: %d \n",  wtimes[counter], rtimes[counter], ttime);
		}
    }    
  exit();
}
